#include "stdafx.h"
#include "DataStream.h"
#include "PreHeader.h"

boost::shared_ptr<DataStream> g_ds;

struct MeshStr
{
	MeshStr()
		:verts(NULL),
		weights(NULL),
		vertices(NULL),
		indexs(NULL),
		texs(NULL),
		texture("")
	{
	}
	Verts* verts;
	Weights* weights;
	Vertices* vertices;
	Indexs* indexs;
	Texs* texs;
	string texture;
};

struct Hierarchy
{
	string name;
	int parentID;

	int flags;
	int startIndex;
};

typedef Vector<Hierarchy*> Hierarchies;

Vector<MeshStr*> g_meshs;
Bones g_basicFrame;
Anims g_anims;

bool LoadMD5Model(string filename)
{
	int numJoints=0;
	int numSubsets=0;
	ifstream fileIn (filename.c_str());		// Open file
	
	string checkString;						// Stores the next string from our file

	if(fileIn)										// Check if the file was opened
	{
		while(fileIn)								// Loop until the end of the file is reached
		{	
			fileIn >> checkString;					// Get next string from file

			if(checkString == "MD5Version")		// Get MD5 version (this function supports version 10)
			{
				fileIn >> checkString;
				/*MessageBox(0, checkString.c_str(),	//display message
				"MD5Version", MB_OK);*/
			}
			else if ( checkString == "commandline" )
			{
				getline(fileIn, checkString);	// Ignore the rest of this line
			}
			else if ( checkString == "numJoints" )
			{
				fileIn >> numJoints;		// Store number of joints
			}
			else if ( checkString == "numMeshes" )
			{
				fileIn >> numSubsets;		// Store number of meshes or subsets which we will call them
			}
			else if ( checkString == "joints" )
			{

				fileIn >> checkString;				// Skip the "{"

				for(int i = 0; i < numJoints; i++)
				{
					
					Bone* tempBone=new Bone;
					string name;
					fileIn >> name;		// Store joints name
					// Sometimes the names might contain spaces. If that is the case, we need to continue
					// to read the name until we get to the closing " (quotation marks)
					if(name[name.size()-1] != '"')
					{
						char checkChar;
						bool jointNameFound = false;
						while(!jointNameFound)
						{
							checkChar = fileIn.get();

							if(checkChar == '"')
								jointNameFound = true;		

							name += checkChar;															
						}
					}

					fileIn >> checkString;	// Store Parent joint's ID

					fileIn >> checkString;			// Skip the "("

					// Store position of this joint (swap y and z axis if model was made in RH Coord Sys)
					fileIn >> tempBone->pos.x >> tempBone->pos.z >> tempBone->pos.y;

					fileIn >> checkString >> checkString;	// Skip the ")" and "("

					// Store orientation of this joint
					fileIn >> tempBone->orientation.x >> tempBone->orientation.z >> tempBone->orientation.y;

					// Compute the w axis of the quaternion (The MD5 model uses a 3D Vector to describe the
					// direction the bone is facing. However, we need to turn this into a quaternion, and the way
					// quaternions work, is the xyz values describe the axis of rotation, while the w is a value
					// between 0 and 1 which describes the angle of rotation)
					float t = 1.0f - ( tempBone->orientation.x * tempBone->orientation.x )
						- ( tempBone->orientation.y * tempBone->orientation.y )
						- ( tempBone->orientation.z * tempBone->orientation.z );
					if ( t < 0.0f )
					{
						tempBone->orientation.w = 0.0f;
					}
					else
					{
						tempBone->orientation.w = -sqrtf(t);
					}

					getline(fileIn, checkString);		// Skip rest of this line

					g_basicFrame.push_back(tempBone);	// Store the joint into this models joint Vector
				}

				fileIn >> checkString;					// Skip the "}"
			}
			else if ( checkString == "mesh")
			{
				MeshStr* subset=new MeshStr;
				int numVerts, numTris, numWeights;

				fileIn >> checkString;					// Skip the "{"

				fileIn >> checkString;
				while ( checkString != "}" )			// Read until '}'
				{
					// In this lesson, for the sake of simplicity, we will assume a textures filename is givin here.
					// Usually though, the name of a material (stored in a material library. Think back to the lesson on
					// loading .obj files, where the material library was contained in the file .mtl) is givin. Let this
					// be an exercise to load the material from a material library such as obj's .mtl file, instead of
					// just the texture like we will do here.
					if(checkString == "shader")		// Load the texture or material
					{						
						string fileNamePath;
						fileIn >> fileNamePath;			// Get texture's filename

						// Take spaces into account if filename or material name has a space in it
						if(fileNamePath[fileNamePath.size()-1] != '"')
						{
							char checkChar;
							bool fileNameFound = false;
							while(!fileNameFound)
							{
								checkChar = fileIn.get();

								if(checkChar == '"')
									fileNameFound = true;

								fileNamePath += checkChar;																	
							}
						}

						// Remove the quotation marks from texture path
						fileNamePath.erase(0, 1);
						fileNamePath.erase(fileNamePath.size()-1, 1);

						subset->texture=fileNamePath;
						//check if this texture has already been loaded

						getline(fileIn, checkString);				// Skip rest of this line
					}
					else if ( checkString == "numverts")
					{
						subset->verts=new Verts;
						subset->texs=new Texs;
						fileIn >> numVerts;								// Store number of vertices

						getline(fileIn, checkString);				// Skip rest of this line

						for(int i = 0; i < numVerts; i++)
						{
							Vert* tempVert=new Vert;
							XMFLOAT2 tempTex;
							fileIn >> checkString						// Skip "vert # ("
								>> checkString
								>> checkString;

							fileIn >> tempTex.x;				// Store tex coords
							fileIn >> tempTex.y;	

							fileIn >> checkString;						// Skip ")"

							fileIn >> tempVert->start;				// Index of first weight this vert will be weighted to

							fileIn >> tempVert->count;				// Number of weights for this vertex

							getline(fileIn, checkString);			// Skip rest of this line

							subset->verts->push_back(tempVert);		// Push back this vertex into subsets vertex Vector
							subset->texs->push_back(tempTex);
						}
					}
					else if ( checkString == "numtris")
					{
						fileIn >> numTris;
						subset->indexs=new Indexs;
						getline(fileIn, checkString);				// Skip rest of this line

						for(int i = 0; i < numTris; i++)				// Loop through each triangle
						{
							unsigned int tempIndex;
							fileIn >> checkString;						// Skip "tri"
							fileIn >> checkString;						// Skip tri counter

							for(int k = 0; k < 3; k++)					// Store the 3 indices
							{
								fileIn >> tempIndex;
								subset->indexs->push_back(tempIndex);
							}

							getline(fileIn, checkString);			// Skip rest of this line
						}
					}
					else if ( checkString == "numweights")
					{
						fileIn >> numWeights;
						
						getline(fileIn, checkString);				// Skip rest of this line

						subset->weights=new Weights;
						for(int i = 0; i < numWeights; i++)
						{
							Weight* tempWeight=new Weight;
							fileIn >> checkString >> checkString;		// Skip "weight #"

							fileIn >> tempWeight->boneId;				// Store weight's joint ID

							fileIn >> tempWeight->bias;					// Store weight's influence over a vertex

							fileIn >> checkString;						// Skip "("

							fileIn >> tempWeight->pos.x					// Store weight's pos in joint's local space
								>> tempWeight->pos.z
								>> tempWeight->pos.y;

							getline(fileIn, checkString);			// Skip rest of this line

							subset->weights->push_back(tempWeight);		// Push back tempWeight into subsets Weight array
						}

					}
					else
						getline(fileIn, checkString);				// Skip anything else

					fileIn >> checkString;								// Skip "}"
				}
				
				g_meshs.push_back(subset);
			}
		}
	}
	else
	{
		return false;
	}

	return true;
}


///////////////**************new**************////////////////////
bool LoadMD5Anim(string filename)
{
	
	Hierarchies tmpHierarchies;
	AnimStr* tmpAnim=new AnimStr;
	tmpAnim->keyFrames=new KeyFrame;
	size_t pos=filename.find_last_of(".");
	Bones basicFrames;
	tmpAnim->animName=filename.substr(0,pos);

	int numFrames=0;
	int numBones=0;
	int numAnimatedComponents=0;
	
	ifstream fileIn (filename.c_str());		// Open file

	string checkString;						// Stores the next string from our file

	if(fileIn)										// Check if the file was opened
	{
		while(fileIn)								// Loop until the end of the file is reached
		{	
			fileIn >> checkString;					// Get next string from file

			if ( checkString == "MD5Version" )		// Get MD5 version (this function supports version 10)
			{
				fileIn >> checkString;
				/*MessageBox(0, checkString.c_str(),	//display message
				"MD5Version", MB_OK);*/
			}
			else if ( checkString == "commandline" )
			{
				getline(fileIn, checkString);	// Ignore the rest of this line
			}
			else if ( checkString == "numFrames" )
			{
				fileIn >> numFrames;				// Store number of frames in this animation
			}
			else if ( checkString == "numJoints" )
			{
				fileIn >> numBones;				// Store number of joints (must match .md5mesh)
			}
			else if ( checkString == "frameRate" )
			{
				fileIn >> tmpAnim->frameRate;				// Store animation's frame rate (frames per second)
			}
			else if ( checkString == "numAnimatedComponents" )
			{
				fileIn >> numAnimatedComponents;	// Number of components in each frame section
			}
			else if ( checkString == "hierarchy" )
			{
				fileIn >> checkString;				// Skip opening bracket "{"

				for(int i = 0; i < numBones; i++)	// Load in each joint
				{
					string name;

					fileIn >> name;		// Get joints name
					// Sometimes the names might contain spaces. If that is the case, we need to continue
					// to read the name until we get to the closing " (quotation marks)
					if(name[name.size()-1] != '"')
					{
						char checkChar;
						bool jointNameFound = false;
						while(!jointNameFound)
						{
							checkChar = fileIn.get();

							if(checkChar == '"')
								jointNameFound = true;		

							name += checkChar;															
						}
					}

					// Remove the quotation marks from joints name
					name.erase(0, 1);
					name.erase(name.size()-1, 1);

					Hierarchy* tmpHierarchy=new Hierarchy;
					tmpHierarchy->name=name;
					fileIn >> tmpHierarchy->parentID;			// Get joints parent ID
					fileIn >> tmpHierarchy->flags;				// Get flags
					fileIn >> tmpHierarchy->startIndex;			// Get joints start index

					tmpHierarchies.push_back(tmpHierarchy);
					getline(fileIn, checkString);		// Skip rest of this line
				}
			}
			else if ( checkString == "bounds" )			// Load in the AABB for each animation
			{
				fileIn >> checkString;						// Skip opening bracket "{"

				for(int i = 0; i < numFrames; i++)
				{
					getline(fileIn,checkString);
				}
			}			
			else if ( checkString == "baseframe" )			// This is the default position for the animation
			{												// All frames will build their skeletons off this
				fileIn >> checkString;						// Skip opening bracket "{"
	
				for(int i = 0; i < numBones; i++)
				{
					Bone* tempBone=new Bone;

					fileIn >> checkString;						// Skip "("
					fileIn >> tempBone->pos.x >> tempBone->pos.z >> tempBone->pos.y;
					fileIn >> checkString >> checkString;		// Skip ") ("
					fileIn >> tempBone->orientation.x >> tempBone->orientation.z >> tempBone->orientation.y;
					fileIn >> checkString;						// Skip ")"

					basicFrames.push_back(tempBone);
				}
			}
			else if ( checkString == "frame" )		// Load in each frames skeleton (the parts of each joint that changed from the base frame)
			{
				
				Bones* tmpFrame=new Bones;
				Bones* resultBones=new Bones;
				fileIn >> checkString;	
				fileIn >> checkString;				// Skip opening bracket "{"

				for(int i = 0; i < numAnimatedComponents/6; i++)
				{
					
					Bone* tmpBone=new Bone;
					fileIn >> tmpBone->pos.x;
					fileIn >> tmpBone->pos.z;
					fileIn >> tmpBone->pos.y;
					
					fileIn >> tmpBone->orientation.x;
					fileIn >> tmpBone->orientation.z;
					fileIn >> tmpBone->orientation.y;

					tmpFrame->push_back(tmpBone);
				}


				for(int i = 0; i < tmpHierarchies.size(); i++)
				{
				
					Bone* resultBone =new Bone;
					resultBone->pos= basicFrames[i]->pos;
					resultBone->orientation=basicFrames[i]->orientation;

					int k = 0;

					if(tmpHierarchies[i]->flags & 1)
						resultBone->pos.x=(*tmpFrame)[i]->pos.x;
					if(tmpHierarchies[i]->flags & 2)
						resultBone->pos.z=(*tmpFrame)[i]->pos.z;
					if(tmpHierarchies[i]->flags & 4)
						resultBone->pos.y=(*tmpFrame)[i]->pos.y;
					if(tmpHierarchies[i]->flags & 8)
						resultBone->orientation.x=(*tmpFrame)[i]->orientation.x;
					if(tmpHierarchies[i]->flags & 16)
						resultBone->orientation.z=(*tmpFrame)[i]->orientation.z;
					if(tmpHierarchies[i]->flags & 32)
						resultBone->orientation.y=(*tmpFrame)[i]->orientation.y;

					float t = 1.0f - ( resultBone->orientation.x * resultBone->orientation.x )
						- ( resultBone->orientation.y * resultBone->orientation.y )
						- ( resultBone->orientation.z * resultBone->orientation.z );
					if ( t < 0.0f )
					{
						resultBone->orientation.w = 0.0f;
					}
					else
					{
						resultBone->orientation.w = -sqrtf(t);
					}
					
					if(tmpHierarchies[i]->parentID >= 0)
					{
						
						Bone* parentBone = (*resultBones)[tmpHierarchies[i]->parentID];

						// Turn the XMFLOAT3 and 4's into vectors for easier computation
						XMVECTOR parentBoneOrientation = 
							XMVectorSet(parentBone->orientation.x, parentBone->orientation.y, parentBone->orientation.z, parentBone->orientation.w);
						XMVECTOR tempBonePos = XMVectorSet(resultBone->pos.x, resultBone->pos.y, resultBone->pos.z, 0.0f);
						XMVECTOR parentOrientationConjugate = 
							XMVectorSet(-parentBone->orientation.x, -parentBone->orientation.y, -parentBone->orientation.z, parentBone->orientation.w);

						// Calculate current joints position relative to its parents position
						XMFLOAT3 rotatedPos;
						XMStoreFloat3(&rotatedPos, XMQuaternionMultiply(XMQuaternionMultiply(parentBoneOrientation, tempBonePos), parentOrientationConjugate));

						// Translate the joint to model space by adding the parent joint's pos to it
						resultBone->pos.x = rotatedPos.x + parentBone->pos.x;
						resultBone->pos.y = rotatedPos.y + parentBone->pos.y;
						resultBone->pos.z = rotatedPos.z + parentBone->pos.z;

						// Currently the joint is oriented in its parent joints space, we now need to orient it in
						// model space by multiplying the two orientations together (parentOrientation * childOrientation) <- In that order
						XMVECTOR tempBoneOrient =
							XMVectorSet(resultBone->orientation.x, resultBone->orientation.y, resultBone->orientation.z, resultBone->orientation.w);
						tempBoneOrient = XMQuaternionMultiply(parentBoneOrientation, tempBoneOrient);

						// Normalize the orienation quaternion
						tempBoneOrient = XMQuaternionNormalize(tempBoneOrient);

						XMStoreFloat4(&resultBone->orientation, tempBoneOrient);
					}

					resultBones->push_back(resultBone);

				}

				fileIn >> checkString;				// Skip closing bracket "}"
				
				tmpAnim->keyFrames->push_back(resultBones);
			}

			
		}
		g_anims.push_back(tmpAnim);

						// Push back the animation into our model object
	}
	else	// If the file was not loaded
	{
		return false;
	}
	return true;
}

Chunk* StoreToData(const string& modelName, bool staticMesh = true)
{
	Chunk* mainChunk;
	Vector<Chunk*> subChunk;
	for(Vector<MeshStr*>::iterator iter=g_meshs.begin();iter!=g_meshs.end();iter++)
	{
		Vector<Chunk*> subMeshChunk;
		MeshStr* tmpMesh=*iter;
		if(staticMesh)
		{
			if(tmpMesh->vertices==NULL)
			{
				Verts* tmpVerts=tmpMesh->verts;
				tmpMesh->vertices=new Vertices;
				Vertices* tmpVertices=tmpMesh->vertices;
				for(VertsIter iverts=tmpVerts->begin();iverts!=tmpVerts->end();iverts++)
				{
					XMFLOAT3 tmpPos(0,0,0);

					for(int i=0;i<(*iverts)->count;i++)
					{
						Weight* tmpWeight = (*iter)->weights->at((*iverts)->start+i);
						Bone* tmpBone = g_basicFrame[tmpWeight->boneId];
						
						XMVECTOR tempBoneOrientation =
							XMVectorSet(tmpBone->orientation.x, tmpBone->orientation.y, tmpBone->orientation.z, tmpBone->orientation.w);
						XMVECTOR tempWeightPos = XMVectorSet(tmpWeight->pos.x, tmpWeight->pos.y, tmpWeight->pos.z, 0.0f);

						XMVECTOR tempBoneOrientationConjugate = 
							XMVectorSet(-tmpBone->orientation.x, -tmpBone->orientation.y, -tmpBone->orientation.z, tmpBone->orientation.w);

						XMFLOAT3 rotatedPoint;
						XMStoreFloat3(&rotatedPoint, XMQuaternionMultiply(XMQuaternionMultiply(tempBoneOrientation, tempWeightPos), tempBoneOrientationConjugate));

						tmpPos.x += ( tmpBone->pos.x + rotatedPoint.x ) * tmpWeight->bias;
						tmpPos.y += ( tmpBone->pos.y + rotatedPoint.y ) * tmpWeight->bias;
						tmpPos.z += ( tmpBone->pos.z + rotatedPoint.z ) * tmpWeight->bias;
					}

					tmpVertices->push_back(tmpPos);
				}
			}
			int numVertices=tmpMesh->vertices->size();
			size_t size=numVertices*sizeof(XMFLOAT3);
			char* data=new char[size];
			char* p=data;
			for(Vertices::iterator iterVertices=tmpMesh->vertices->begin();iterVertices!=tmpMesh->vertices->end();iterVertices++)
			{
				memcpy(p,(XMFLOAT3*)(&*iterVertices),sizeof(XMFLOAT3));
				p+=sizeof(XMFLOAT3);
			}
			Chunk* tmp=new Chunk("vertices",size,data);
			subMeshChunk.push_back(tmp);
		}
		else
		{
			if(tmpMesh->weights==NULL)
				EXCEPTION("")
			Vector<Chunk*> subWeights;
			for(WeightsIter iterWeight=tmpMesh->weights->begin();iterWeight!=tmpMesh->weights->end();iterWeight++)
			{
				Vector<Chunk*> preWeight;
				Weight* tmpWeight=*iterWeight;
				char* data=new char[sizeof(Weight)];
				char* p=data;
				memcpy(p,&tmpWeight->bias,sizeof(float));
				p+=sizeof(float);
				memcpy(p,&tmpWeight->boneId,sizeof(int));
				p+=sizeof(int);
				memcpy(p,&tmpWeight->pos,sizeof(XMFLOAT3));
				p+=sizeof(XMFLOAT3);
				subWeights.push_back(new Chunk("weight",sizeof(Weight),data));
			}
			Chunk* tmp=new Chunk("weights",subWeights);
			subMeshChunk.push_back(tmp);
			
			if(tmpMesh->verts==NULL)
				EXCEPTION("")
			int numVerts=tmpMesh->verts->size();
			size_t size=numVerts*sizeof(Vert);
			char* data=new char[size];
			char* p=data;
			for(VertsIter iterVerts=tmpMesh->verts->begin();iterVerts!=tmpMesh->verts->end();iterVerts++)
			{
				memcpy(p,&(*iterVerts)->start,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,&(*iterVerts)->count,sizeof(unsigned int));
				p+=sizeof(unsigned int);
			}
			tmp=new Chunk("verts",size,data);
			subMeshChunk.push_back(tmp);
		}

		if(tmpMesh->indexs==NULL)
			EXCEPTION("")
		
		int numIndexs=tmpMesh->indexs->size();
		size_t size=numIndexs*sizeof(unsigned int);
		char* data=new char[size];
		char* p=data;
		for(IndexsIter iterIndexs=tmpMesh->indexs->begin();iterIndexs!=tmpMesh->indexs->end();iterIndexs++)
		{
			memcpy(p,(unsigned int*)(&*iterIndexs),sizeof(unsigned int));
			p+=sizeof(unsigned int);
		}
		Chunk* tmp=new Chunk("indexs",size,data);
		subMeshChunk.push_back(tmp);
		
		if(tmpMesh->texs==NULL)
			EXCEPTION("")
		int numTexs=tmpMesh->texs->size();
		
		size=numTexs*sizeof(XMFLOAT2);
		data=new char[size];
		p=data;
		for(TexsIter iterTexs=tmpMesh->texs->begin();iterTexs!=tmpMesh->texs->end();iterTexs++)
		{
			memcpy(p,(XMFLOAT2*)(&*iterTexs),sizeof(XMFLOAT2));
			p+=sizeof(XMFLOAT2);
		}
		tmp=new Chunk("texs",size,data);
		subMeshChunk.push_back(tmp);
		
		if(tmpMesh->texture=="")
			EXCEPTION("")
		
		size=tmpMesh->texture.length()+1;
		data=new char[size];
		strcpy_s(data,size,tmpMesh->texture.c_str());
		tmp=new Chunk("texture",size,data);
		subMeshChunk.push_back(tmp);
		subChunk.push_back(new Chunk("submesh",subMeshChunk));
	}
	
	if(!staticMesh)
	{
		if(g_anims.empty())
			EXCEPTION("")
		
		Vector<Chunk*> tmpAnimChunk;
		for(AnimsIter iter=g_anims.begin();iter!=g_anims.end();iter++)
		{
			Chunk* tmpName=new Chunk("animName",(*iter)->animName.size()+1,(*iter)->animName.c_str());
			char* data=new char[sizeof(int)];
			memcpy(data,&(*iter)->frameRate,sizeof(int));
			Chunk* tmpFrameRate=new Chunk("frameRate",sizeof(int),data);
			Vector<Chunk*> tmpKeyFramesChunk;
			for(KeyFrameIter kiter=(*iter)->keyFrames->begin();kiter!=(*iter)->keyFrames->end();kiter++)
			{
				Vector<Chunk*> tmpPreFramesChunk;
				for(BonesIter biter=(*kiter)->begin();biter!=(*kiter)->end();biter++)
				{
					int i=sizeof(Bone);
					char* boneData=new char[sizeof(Bone)];
					char* t=boneData;
					memcpy(t,&(*biter)->pos,sizeof(XMFLOAT3));
					t+=sizeof(XMFLOAT3);
					memcpy(t,&(*biter)->orientation,sizeof(XMFLOAT4));
					t+=sizeof(XMFLOAT4);
					tmpPreFramesChunk.push_back(new Chunk("bone",sizeof(Bone),boneData));
				}
				tmpKeyFramesChunk.push_back(new Chunk("frame",tmpPreFramesChunk));
			}
			tmpAnimChunk.push_back(tmpName);
			tmpAnimChunk.push_back(tmpFrameRate);
			tmpAnimChunk.push_back(new Chunk("frames",tmpKeyFramesChunk));

		}

		subChunk.push_back(new Chunk("anim",tmpAnimChunk));
		subChunk.push_back(new Chunk("usage",10,"animation"));

	}
	else
	{
		subChunk.push_back(new Chunk("usage",7,"static"));
	}

	mainChunk=new Chunk("mesh",subChunk);

	return mainChunk;
}

int main(int argc, char* argv[])
{
	//DataStream ds("temp.txt",DataStream::READ_ONLY);
	if(argc<2)
	{
		cout<<"Command line error!"<<endl;
		return -1;
	}
	
	string modelName=argv[1];
	
	bool loadOkay = LoadMD5Model(modelName);

	if (!loadOkay)
	{
		cout<<"Failed to load mesh file "<<argv[1]<<endl;
		return -1;
	}
	if(argc>2)
	{
		for(int i=2;i<argc;i++)
		{
			string animName=argv[i];
			bool rt= LoadMD5Anim(animName);
			if(!rt)
				EXCEPTION("")
		}
	}
	Chunk* mainChunk;
	try
	{
		if (g_anims.empty())
		{
			mainChunk=StoreToData(modelName,true);
		}
		else
		{
			mainChunk=StoreToData(modelName,false);
		}
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e);
	}

	size_t pos=modelName.find_last_of(".");
	string storeName=modelName.substr(0,pos);
	storeName+=".data";
	g_ds=boost::make_shared<DataStream>(storeName,storeName,GEN_VERSION(1,1),mainChunk);
	g_ds->Save();
	return 0;
}
